
package org.dufeng.app.locktool;

import android.app.Dialog;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout;

public class MainService extends Service {
    static final String TAG = "MainService";

    LayoutInflater mLayoutInflater;
    WindowManager mWindowManager;
    FrameLayout mRootLayout;
    ImageView mBtnView;
    int mLastStartId;
    boolean mFloatIsVisable;
    boolean mIsLockKey;
    boolean mIsLockTouch;
    boolean mIsLockVolKey;
    boolean mLockTouchChanged = false;

    int mFloatX = 0;
    int mFloatY = 0;

    LayoutParams mLayoutParams = new LayoutParams();

    Dialog mSettingDialog;

    float mLastTouchX;
    float mLastTouchY;
    float mTotalOffset;
    long mTouchDownTime;

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        mLayoutInflater = LayoutInflater.from(getApplicationContext());
        mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        mRootLayout = new MyRootLayout(getApplicationContext());
        mRootLayout.setId(R.layout.float_layout);
        // mRootLayout = (FrameLayout)
        // mLayoutInflater.inflate(R.layout.float_layout, null);
        mBtnView = new ImageView(getApplicationContext());
        mBtnView.setId(R.id.buttonMain);
        mBtnView.setImageResource(R.drawable.float_normal);

        mBtnView.setOnTouchListener(mButtonTouchListener);
        mBtnView.setOnClickListener(mButtonClickListener);
        mBtnView.setOnKeyListener(mOnKeyListener);
        mRootLayout.addView(mBtnView, ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);

        mRootLayout.setOnTouchListener(mRootTouchListener);
        // mRootLayout.setOnKeyListener(mOnKeyListener);

        mSettingDialog = new Dialog(getApplication(), R.style.MainDialog);
        mSettingDialog.getWindow().setType(LayoutParams.TYPE_SYSTEM_ALERT);
        View v = mLayoutInflater.inflate(R.layout.setting_layout, null);
        CheckBox cbLockKey = (CheckBox) v.findViewById(R.id.checkLockKey);
        CheckBox cbLockTouch = (CheckBox) v.findViewById(R.id.checkLockTouch);
        cbLockKey.setOnCheckedChangeListener(mCheckedChangeListener);
        cbLockTouch.setOnCheckedChangeListener(mCheckedChangeListener);
        v.findViewById(R.id.buttonOk).setOnClickListener(mButtonClickListener);
        v.findViewById(R.id.buttonExit).setOnClickListener(mButtonClickListener);
        Resources res = getResources();
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                (int) res.getDimension(R.dimen.float_width),
                (int) res.getDimension(R.dimen.float_height));
        mSettingDialog.addContentView(v, lp);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public enum Action {
        LockKey, UnLockKey, LockTouch, UnLockTouch, Show, Exit,
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mLastStartId = startId;
        String action = intent.getAction();
        if (action != null) {
            Action a = Action.valueOf(action);
            if (a != null) {
                handleAction(a);
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    void handleAction(Action action) {

        switch (action) {
            case Show:
                setFloatVisable(true);
                break;
            case Exit:
                setFloatVisable(false);
                stopSelf();
                break;
            case LockKey:
                setLockKey(true);
                break;
            case UnLockKey:
                setLockKey(false);
                break;
            case LockTouch:
                setLockTouch(true);
                break;
            case UnLockTouch:
                setLockTouch(false);
                break;
            default:
                break;
        }
    }

    private void setFloatVisable(boolean visable) {
        if (mFloatIsVisable != visable) {
            if (visable) {
                mWindowManager.addView(mRootLayout, getLayoutParams());
            } else {
                mWindowManager.removeView(mRootLayout);
            }
            mFloatIsVisable = visable;
        }
    }

    private void setLockKey(boolean lock) {
        if (mIsLockKey != lock) {
            mIsLockKey = lock;
            updateFloatLayout();
        }

    }

    private void setLockTouch(boolean lock) {
        if (mIsLockTouch != lock) {
            mIsLockTouch = lock;
            mLockTouchChanged = true;
            updateFloatLayout();
            mLockTouchChanged = false;
        }
    }

    private void updateFloatLayout() {
        if (mIsLockTouch) {
            mBtnView.setX(mFloatX);
            mBtnView.setY(mFloatY);
        } else {
            mBtnView.setX(0);
            mBtnView.setY(0);
        }
        mWindowManager.updateViewLayout(mRootLayout, getLayoutParams());
    }

    static final int FLAG_NO_LOCK = LayoutParams.FLAG_NOT_TOUCH_MODAL
            | LayoutParams.FLAG_NOT_FOCUSABLE;

    static final int FLAG_LOCK_KEY = LayoutParams.FLAG_NOT_TOUCH_MODAL;

    public WindowManager.LayoutParams getLayoutParams() {
        final LayoutParams lp = mLayoutParams;
        lp.type = LayoutParams.TYPE_SYSTEM_ALERT;
        // lp.type = LayoutParams.TYPE_NAVIGATION_BAR;
        lp.format = PixelFormat.RGBA_8888;
        lp.flags = mIsLockKey ? FLAG_LOCK_KEY : FLAG_NO_LOCK;
        lp.gravity = Gravity.TOP | Gravity.LEFT;

        if (mIsLockTouch) {
            lp.width = LayoutParams.MATCH_PARENT;
            lp.height = LayoutParams.MATCH_PARENT;
            lp.x = 0;
            lp.y = 0;
        } else {
            lp.width = LayoutParams.WRAP_CONTENT;
            lp.height = LayoutParams.WRAP_CONTENT;
            lp.x = mFloatX;
            lp.y = mFloatY;
        }

        return lp;
    }

    OnClickListener mButtonClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.buttonMain:
                    showSettingDialog();
                    break;
                case R.id.buttonExit:
                    handleAction(Action.Exit);
                    hideSettingDialog();
                    break;
                case R.id.buttonOk:
                    hideSettingDialog();
                    break;
            }
        }
    };

    OnTouchListener mButtonTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent e) {
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mLastTouchX = e.getRawX();
                    mLastTouchY = e.getRawY();
                    mTouchDownTime = System.currentTimeMillis();
                    mTotalOffset = 0;
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_MOVE: {
                    float x = e.getRawX();
                    float y = e.getRawY();

                    float offsetX = x - mLastTouchX;
                    float offsetY = y - mLastTouchY;

                    long offsetTime = System.currentTimeMillis() - mTouchDownTime;

                    mTotalOffset += Math.abs(offsetX) + Math.abs(offsetY);

                    mLastTouchX = x;
                    mLastTouchY = y;

                    if (mTotalOffset < mBtnView.getWidth() / 2 && offsetTime < 500L) {
                        break;
                    }

                    mBtnView.setPressed(false);

                    mFloatX += offsetX;
                    mFloatY += offsetY;
                    updateFloatLayout();

                    return true;
                }
            }
            return false;
        }
    };
    OnTouchListener mRootTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent e) {
            switch (e.getAction()) {
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mBtnView.setImageResource(R.drawable.float_normal);
                    break;
                default:
                    mBtnView.setImageResource(R.drawable.main_float_lock);
                    break;
            }
            return false;
        }
    };

    OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton v, boolean checked) {
            switch (v.getId()) {
                case R.id.checkLockKey:
                    handleAction(checked ? Action.LockKey : Action.UnLockKey);
                    break;
                case R.id.checkLockTouch:
                    handleAction(checked ? Action.LockTouch : Action.UnLockTouch);
                    break;
            }
        }
    };

    OnKeyListener mOnKeyListener = new OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            Log.d(TAG, "keyCode = " + keyCode);
            return false;
        }
    };

    void showSettingDialog() {
        if (!mSettingDialog.isShowing()) {
            mSettingDialog.show();
        }
    }

    void hideSettingDialog() {
        if (mSettingDialog.isShowing()) {
            mSettingDialog.dismiss();
        }
    }

    class MyRootLayout extends FrameLayout {

        public MyRootLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        public MyRootLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public MyRootLayout(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            Log.d(TAG, "MyRootLayout onKeyEvent code=" + event.getKeyCode());
            if (mIsLockKey || mIsLockVolKey) {
                if (event.getAction() == KeyEvent.ACTION_UP) {
                    mBtnView.setImageResource(R.drawable.float_normal);
                } else {
                    mBtnView.setImageResource(R.drawable.main_float_lock);
                }
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_VOLUME_DOWN:
                    case KeyEvent.KEYCODE_VOLUME_UP:
                        if (mIsLockVolKey) {
                            return true;
                        }
                        break;
                    default:
                        if (mIsLockKey) {
                            return true;
                        }
                        break;
                }
            }
            return super.dispatchKeyEvent(event);
        }

        @Override
        public boolean dispatchKeyEventPreIme(KeyEvent event) {
            // TODO Auto-generated method stub
            return super.dispatchKeyEventPreIme(event);
        }

    }
}
